package com.smartStatus.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smartStatus.admin.mapper.SysMenuMapper;
import com.smartStatus.admin.mapper.SysRoleMapper;
import com.smartStatus.admin.service.SysMenuPermissionService;
import com.smartStatus.admin.service.SysMenuService;
import com.smartStatus.admin.service.SysRoleService;
import com.smartStatus.admin.utils.JoinUtil;
import com.smartStatus.api.entity.SysMenu;
import com.smartStatus.api.entity.SysMenuPermission;
import com.smartStatus.api.entity.SysRole;
import com.smartStatus.api.entity.SysUser;
import com.smartStatus.api.vo.SysMenuVo;
import com.smartStatus.api.vo.TreeNodeVo;
import com.smartStatus.core.util.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;

import javax.swing.tree.TreeNode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName : SysRoleServiceImpl
 * @Author : lby
 * @Date: 2020/12/29 10:09
 * @Description :
 */
@Service
@AllArgsConstructor
@Slf4j
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {
    private final SysMenuMapper sysMenuMapper;
    private final SysMenuPermissionService sysMenuPermissionService;

    @Override
    public SysRole getRoleInfo(Integer id) {
        return baseMapper.getRoleInfo(id);
    }


    @Override
    public Boolean delRole(Integer id) {
        return baseMapper.delRole(id);
    }

    @Override
    public Boolean addRoleMenus(Integer id, @Param("menuId") Integer menuId) {
        return baseMapper.addRoleMenus(id, menuId);
    }

    @Override
    public List<Integer> getMenuIds(SysRole sysRole) {
        return baseMapper.getMenuIds(sysRole);
    }

    @Override
    public Boolean delMenus(Integer id) {
        return baseMapper.delMenus(id);
    }

    @Override
    public List<SysRole> getUserRoleLists(SysUser sysUser) {
        return baseMapper.getUserRoleLists(sysUser);
    }

    @Override
    public Boolean delUserRoleList(SysUser sysUser) {
        return baseMapper.delUserRoleList(sysUser);
    }


    @Override
    public R getPermissionTree(String parentId) {
        Map<String, Object> dataMap = new HashMap<>();
        List<Map<String, Object>> list = new ArrayList<>();
        List<String> checkedIdList = new ArrayList<>();
        QueryWrapper<SysMenu> sysMenuQueryWrapper = Wrappers.query();
        sysMenuQueryWrapper.eq("menu_parent_id", parentId);
        List<SysMenu> menuList = sysMenuMapper.selectList(sysMenuQueryWrapper);
        // 如果可以获取到子菜单，继续向下，如果未获取，则需要查询菜单对应的权限
        if (menuList != null && menuList.size() > 0) {
            for (SysMenu x : menuList) {
                Map<String, Object> map = new HashMap<>();
                map.put("leaf", true);
                // 判断子节点有没有下一次，包括下一层菜单和下一层权限
                QueryWrapper<SysMenu> countQuery = Wrappers.query();
                countQuery.eq("menu_parent_id", x.getId());
                List<SysMenu> menuList1 = sysMenuMapper.selectList(countQuery);
                if (menuList1 != null && menuList1.size() > 0) {
                    map.put("leaf", false);
                } else {
                    QueryWrapper<SysMenuPermission> permissionCount = Wrappers.query();
                    permissionCount.eq("menu_id", x.getId());
                    List<SysMenuPermission> list1 = sysMenuPermissionService.list(permissionCount);
                    if (list1 != null && list1.size() > 0) {
                        map.put("leaf", false);
                    }
                }
                map.put("name", x.getName());
                map.put("children", x.getChildren());
                map.put("id", x.getId());
                checkedIdList.add(x.getId().toString());
                list.add(map);
            }
            dataMap.put("dataList", list);
            dataMap.put("checkedList", checkedIdList);
            return R.ok(dataMap);
        } else {
            // 没查到查权限
            QueryWrapper<SysMenuPermission> query = Wrappers.query();
            query.eq("menu_id", parentId);
            List<SysMenuPermission> list1 = sysMenuPermissionService.list(query);
            if (list1 != null && list1.size() > 0) {
                list1.forEach(x -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("name", x.getPermission());
                    map.put("leaf", true);
                    map.put("children", null);
                    map.put("id", x.getId());
                    checkedIdList.add(x.getId());
                    list.add(map);
                });
            }
            dataMap.put("dataList", list);
            dataMap.put("checkedList", checkedIdList);
            return R.ok(dataMap);
        }

    }


    @Override
    public R buildRoleTree(Integer roleId) {
        QueryWrapper<SysMenu> query = Wrappers.query();
        List<SysMenuVo> menuList = JoinUtil.list(sysMenuMapper.selectList(query), SysMenuVo.class);
//        List<SysMenuVo> menuList = sysMenuMapper.getMenuIdList(roleId.toString());
        if (menuList == null || menuList.size() == 0) {
            return R.failed("未获取到该角色对应的菜单数据");
        }
        List<TreeNodeVo> list = new ArrayList<>();
        menuList.forEach(x -> {
            if (x.getMenuParentId() == 0) {
                TreeNodeVo treeNodeVo = this.transNode(x);
                list.add(treeNodeVo);
            }
        });
        list.forEach(x -> {
            this.rebuild(x, roleId.toString());
        });
        List<Integer> integerList = menuList.stream().map(SysMenuVo::getId).collect(Collectors.toList());
        QueryWrapper<SysMenuPermission> queryWrapper = Wrappers.query();
        queryWrapper.in("menu_id", integerList);
        queryWrapper.eq("checked", "1");
        queryWrapper.eq("role_id", roleId);
        List<SysMenuPermission> list1 = sysMenuPermissionService.list(queryWrapper);
        List<String> collect = new ArrayList<>();
        if (list1 != null && list1.size() > 0) {
            log.info("未获取到该角色对应的菜单权限数据");
            collect = list1.stream().map(SysMenuPermission::getId).collect(Collectors.toList());
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("dataList", list);
        resultMap.put("idList", collect);
        return R.ok(resultMap);
    }

    public TreeNodeVo rebuild(TreeNodeVo treeNodeVo, String roleId) {
        QueryWrapper<SysMenu> sysMenuQueryWrapper = Wrappers.query();
        sysMenuQueryWrapper.eq("menu_parent_id", treeNodeVo.getId());
        List<SysMenu> list1 = sysMenuMapper.selectList(sysMenuQueryWrapper);
        // 没有查到节点，检查权限数据
        if (list1 == null || list1.size() == 0) {
            QueryWrapper<SysMenuPermission> permissionQuery = Wrappers.query();
            permissionQuery.eq("menu_id", treeNodeVo.getId());
            permissionQuery.eq("role_id", roleId);
            List<SysMenuPermission> list = sysMenuPermissionService.list(permissionQuery);
            if (list == null || list.size() == 0) {
                return treeNodeVo;
            }
            List<TreeNodeVo> permissionList = new ArrayList<>();
            list.forEach(x -> {
                TreeNodeVo treeNodeVo1 = new TreeNodeVo();
                treeNodeVo1.setLeaf(true);
                treeNodeVo1.setId(x.getId());
                treeNodeVo1.setName(x.getPermission());
                treeNodeVo1.setFlag("permission");
                treeNodeVo1.setParentId(x.getMenuId().toString());
                permissionList.add(treeNodeVo1);
            });
            treeNodeVo.setChildren(permissionList);
            return treeNodeVo;
        }
        List<SysMenuVo> menuList = JoinUtil.list(list1, SysMenuVo.class);
        List<TreeNodeVo> list = new ArrayList<>();
        if (menuList != null && menuList.size() > 0) {
            menuList.forEach(x -> {
                TreeNodeVo treeNodeVo1 = this.transNode(x);
                list.add(treeNodeVo1);
            });
        }
        treeNodeVo.setChildren(list);
        // 如果存在数据，继续向下轮询子节点
        for (TreeNodeVo vo : list) {
            treeNodeVo = this.rebuild(vo, roleId);
        }
        return treeNodeVo;
    }


    /**
     * 树节点转换
     *
     * @param sysMenuVo
     * @return
     */
    public TreeNodeVo transNode(SysMenuVo sysMenuVo) {
        TreeNodeVo nodeVo = new TreeNodeVo();
        nodeVo.setId(sysMenuVo.getId().toString());
        nodeVo.setName(sysMenuVo.getName());
        nodeVo.setLeaf(false);
        nodeVo.setFlag("menu");
        return nodeVo;
    }


    @Override
    public R addRoelMenuTree(Map<String, Object> map) {
        String checkRoleId = map.get("checkRoleId").toString();
        String checkList = JSON.toJSONString(map.get("checkList"));
        if (StringUtils.isNotBlank(checkList)) {
            List<TreeNodeVo> treeNodeVoList = JSON.parseObject(checkList, new TypeReference<List<TreeNodeVo>>() {
            });
            // 找到添加的数据
            List<TreeNodeVo> treeNodeVos = treeNodeVoList.stream().filter(x -> "permission".equals(x.getFlag())).collect(Collectors.toList());
            List<String> list = treeNodeVos.stream().map(TreeNodeVo::getParentId).collect(Collectors.toList());
            List<SysMenuPermission> sysMenuPermissions = new ArrayList<>();
            // 先把之前的都改了
            QueryWrapper<SysMenuPermission> permissionQuery = Wrappers.query();
            permissionQuery.in("menu_id", list);
            permissionQuery.eq("role_id", checkRoleId);
            SysMenuPermission sysMenuPermission1 = new SysMenuPermission();
            sysMenuPermission1.setChecked("0");
            sysMenuPermissionService.update(sysMenuPermission1, permissionQuery);
            treeNodeVos.forEach(x -> {
                // 修改新的
                permissionQuery.clear();
                SysMenuPermission sysMenuPermission = new SysMenuPermission();
                permissionQuery.eq("permission", x.getName());
                permissionQuery.eq("role_id", checkRoleId);
                sysMenuPermission.setChecked("1");
                sysMenuPermissionService.update(sysMenuPermission, permissionQuery);
            });
            // 添加sys_menu_role
            for (TreeNodeVo t : treeNodeVos) {
                SysMenuPermission byId = sysMenuPermissionService.getById(t.getId());
                Integer menuId = byId.getMenuId();
                this.recursionAddRole(menuId.toString(),checkRoleId);

            }
        }

        // 未选中任何节点
        else {
            sysMenuMapper.batchClearPermission(checkRoleId);
        }
        return R.ok();
    }


    public void recursionAddRole(String menuId, String roleId) {
        if (!"0".equals(menuId)) {
            // 如果已经拥有，不用添加
            Integer countNumber = baseMapper.countNumber(menuId, roleId);
            if (countNumber == 0) {
                // 不包含，需要添加
                baseMapper.addRoleMenus(Integer.parseInt(roleId), Integer.parseInt(menuId));
                // 获取父菜单
                SysMenu sysMenu = sysMenuMapper.selectById(menuId);
                Integer menuParentId = sysMenu.getMenuParentId();
                this.recursionAddRole(menuParentId.toString(), roleId);
            }
        }
    }


    @Override
    public R addRole(SysRole sysRole) {
        // 添加角色
        this.save(sysRole);
        // 添加默认角色和所有菜单相关联
        QueryWrapper<SysMenu> query = Wrappers.query();
        List<SysMenu> menuList = sysMenuMapper.selectList(query);
        menuList.forEach(x -> {
            this.addRoleMenus(sysRole.getId(), x.getId());
        });
        // 添加默认所有权限关联
        QueryWrapper<SysMenuPermission> sysMenuPermissionQueryWrapper = Wrappers.query();
        sysMenuPermissionQueryWrapper.in("menu_id", menuList.stream().map(SysMenu::getId).collect(Collectors.toList()));
        List<SysMenuPermission> list = sysMenuPermissionService.list(sysMenuPermissionQueryWrapper);
        ArrayList<SysMenuPermission> list1 = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<SysMenuPermission>(Comparator.comparing(SysMenuPermission::getPermission))), ArrayList::new));
        list1.forEach(x -> {
            SysMenuPermission sysMenuPermission = new SysMenuPermission();
            sysMenuPermission.setPermission(x.getPermission());
            sysMenuPermission.setMenuId(x.getMenuId());
            sysMenuPermission.setRoleId(sysRole.getId().toString());
            sysMenuPermission.setChecked("0");
            sysMenuPermission.insert();
        });
        return R.ok();
    }
}
